package com.arcticcoding.telemetrie;

import java.io.ByteArrayOutputStream;

import com.arcticcoding.telemetrie.comm.CameraResponse;
import com.arcticcoding.telemetrie.comm.TelemetrieResponse;

import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.util.Log;

/**
 * Implementation of a TelemetrieService which records images 
 * and post them in jpg format.
 * 
 * @author steffenschuhmann
 * @version 1.0
 */
public class CameraService extends TelemetrieService implements PreviewCallback {
	private static final String 		TAG 			= "com.arcticcoding.telemetrie.CameraService";
	private Camera						camera 			= null;
	private TelemetrieProvider 			provider;
	private int 						imageQuality 	= 50;			
	
	/**
	 * Don't call this constructor, needed by the telemetrie provider
	 */
	public CameraService() {
		super();
		super.create();
	}
	
	/**
	 * Create a new CameraService instance with the given provider.
	 * 
	 * @param provider The provider which controls this instance
	 */
	public CameraService(TelemetrieProvider provider) {
		super();
		if(provider == null)
			throw new IllegalArgumentException();
		try {
			this.provider = provider;
			this.camera = Camera.open();
			camera.setPreviewCallback(this);
		} catch(Exception e) {
			e.printStackTrace();
			throw new NullPointerException("No camera instance");
		}
//		Log.d(TAG, "CamerService started");
		super.create();
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean equals(Object o) {
		if(o instanceof CameraService) {
			Log.d(TAG, "Same instance");
			return true;
		} else {
			return false;
		}
	}

	
	 /**
	  * {@inheritDoc}
	  */
	@Override
	public void onPreviewFrame(byte[] data, Camera camera) {
		Camera.Parameters parameters = camera.getParameters();

		int width = parameters.getPreviewSize().width;
		int height = parameters.getPreviewSize().height;

		final ByteArrayOutputStream outstr = new ByteArrayOutputStream();
		Rect rect = new Rect(0, 0, width, height);
		YuvImage yuvimage = new YuvImage(data, ImageFormat.NV21, width, height,
				null);
		yuvimage.compressToJpeg(rect, imageQuality, outstr);

		final TelemetrieResponse value = new CameraResponse(
				CameraResponse.Type.IMAGE_FRAME, outstr.toByteArray());

		new Thread(new Runnable() {
			@Override
			public void run() {
				Log.d(TAG, "Pushing image to provider.");
				provider.valueHasChanged(value);
			}
		}, "ImagePusher").start();
	}
	
	/**
	 * Start the camera stream
	 */
	public void startStreaming() {
		Log.d(TAG, "Start streaming");
		camera.startPreview();
	}
	
	/**
	 * Stop the camera stream
	 */
	public void stopStreaming() {
		Log.d(TAG, "Stop streaming");
		camera.stopPreview();
	}
	
	/**
	 * Put the LED on
	 */
	public void ledOn() {
		Log.d(TAG, "Led on");
		Camera.Parameters params = camera.getParameters();
		
		if(params.getSupportedFlashModes().contains(Camera.Parameters.FLASH_MODE_TORCH)) {
			params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
			camera.setParameters(params);
		} else {
			Log.d(TAG, "LED torch not available");
		}
	}
	
	/**
	 * Put the LED off
	 */
	public void ledOff() {
		Log.d(TAG, "Led off");
		Camera.Parameters params = camera.getParameters();
		
		if(params.getSupportedFlashModes().contains(Camera.Parameters.FLASH_MODE_OFF)) {
			params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
			camera.setParameters(params);
			Log.d(TAG, "Led of");
		} else {
			Log.d(TAG, "Led off not available");
		}
	}
	
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	protected void shutdown() {
		if(camera != null)
			camera.release();
		super.shutdown();
	}
}
